﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data.SqlClient;
using System.Web.Caching;
using System.Web;
using System.Data.Linq;

namespace DataObject.Core
{
    public static class LinqExtensions
    {
        /// <summary>
        /// Sort
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortExpression"></param>
        /// <returns></returns>
        public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class
        {
            if (string.IsNullOrEmpty(sortExpression))
                return source; // nothing to sort on  

            var entityType = typeof(TEntity);
            string ascSortMethodName = "OrderBy";
            string descSortMethodName = "OrderByDescending";
            string[] sortExpressionParts = sortExpression.Split(' ');
            string sortProperty = sortExpressionParts[0];
            string sortMethod = ascSortMethodName;

            if (sortExpressionParts.Length > 1 && sortExpressionParts[1] == "DESC")
                sortMethod = descSortMethodName;

            var property = entityType.GetProperty(sortProperty);
            var parameter = Expression.Parameter(entityType, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExp = Expression.Lambda(propertyAccess, parameter);

            MethodCallExpression resultExp = Expression.Call(
                                                typeof(Queryable),
                                                sortMethod,
                                                new Type[] { entityType, property.PropertyType },
                                                source.Expression,
                                                Expression.Quote(orderByExp)
                                                );

            return source.Provider.CreateQuery<TEntity>(resultExp);
        }
        /// <summary>
        /// Paging
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public static IQueryable<TSource> PageIQuery<TSource>(this IQueryable<TSource> source, int page, int pageSize)
        {
            return source.Skip((page - 1) * pageSize).Take(pageSize).Cast<TSource>();
        }
        public static List<TSource> PageIList<TSource>(this List<TSource> source, int page, int pageSize)
        {
            return source.Skip((page - 1) * pageSize).Take(pageSize).ToList();
        }
        public static List<T> LinqCache<T>(this IQueryable<T> query, Table<T> table, string CacheKey) where T : class
        {
            string tableName = table.Context.Mapping.GetTable(typeof(T)).TableName;
            List<T> result = HttpContext.Current.Cache[CacheKey] as List<T>;
            if (result == null)
            {
                using (SqlConnection cn = new SqlConnection(table.Context.Connection.ConnectionString))
                {
                    cn.Open();
                    SqlCommand cmd = new SqlCommand(table.Context.GetCommand(query).CommandText, cn);
                    cmd.Notification = null;
                    cmd.NotificationAutoEnlist = true;
                    SqlCacheDependencyAdmin.EnableNotifications(table.Context.Connection.ConnectionString);
                    if (!SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(table.Context.Connection.ConnectionString).Contains(tableName))
                    {
                        SqlCacheDependencyAdmin.EnableTableForNotifications(table.Context.Connection.ConnectionString, tableName);
                    }
                    SqlCacheDependency dependency = new SqlCacheDependency(cmd);
                    cmd.ExecuteNonQuery();
                    result = query.ToList();
                    HttpContext.Current.Cache.Insert(tableName, CacheKey, dependency);
                }
            }
            return result;
        }
 
        //public static List<object> LinqCache<TSource>(this IQueryable<TSource> query, string CacheKey)
        //{
        //    using (DC db = new DC())
        //    {
        //        IQueryable<TSource> result = HttpContext.Current.Cache[CacheKey] as IQueryable<TSource>;
        //        if (result == null)
        //        {
        //            using (SqlConnection cn = new SqlConnection(db.Connection.ConnectionString))
        //            {
        //                cn.Open();
        //                SqlCommand cmd = new SqlCommand(db.GetCommand(query).CommandText, cn);
        //                cmd.Notification = null;
        //                cmd.NotificationAutoEnlist = true;
        //                SqlCacheDependency dependency = new SqlCacheDependency(cmd);
        //                cmd.ExecuteNonQuery();
        //                result = query;
        //                HttpContext.Current.Cache.Insert(CacheKey, result, dependency);
        //            }
        //        }
        //        return result;
        //    }
        //}
    }
}
